home *** CD-ROM | disk | FTP | other *** search
/ 3D GFX / 3D GFX.iso / amiutils / m_p / povraywb / source.lzh / pbm.c < prev    next >
C/C++ Source or Header  |  1995-01-30  |  9KB  |  411 lines

  1. /****************************************************************************
  2. *                   pbm.c
  3. *
  4. *  This module contains the code to read and write the ppm file format.
  5. *  The format is as follows:
  6. *
  7. *  (header:)
  8. *    P6              - ppm packed magic
  9. *    wwww hhhh       - Width, Height (16 bits, LSB first)
  10. *    255             - max value
  11. *
  12. *  (each scanline:)
  13. *    llll            - Line number (16 bits, LSB first)
  14. *    rr gg bb        - bytes
  15. *
  16. *  from Persistence of Vision Raytracer
  17. *  Copyright 1993 Persistence of Vision Team
  18. *---------------------------------------------------------------------------
  19. *  NOTICE: This source code file is provided so that users may experiment
  20. *  with enhancements to POV-Ray and to port the software to platforms other 
  21. *  than those supported by the POV-Ray Team.  There are strict rules under
  22. *  which you are permitted to use this file.  The rules are in the file
  23. *  named POVLEGAL.DOC which should be distributed with this file. If 
  24. *  POVLEGAL.DOC is not available or for more info please contact the POV-Ray
  25. *  Team Coordinator by leaving a message in CompuServe's Graphics Developer's
  26. *  Forum.  The latest version of POV-Ray may be found there as well.
  27. *
  28. * This program is based on the popular DKB raytracer version 2.12.
  29. * DKBTrace was originally written by David K. Buck.
  30. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  31. *
  32. *****************************************************************************/
  33.  
  34. #include "frame.h"
  35. #include "povproto.h"
  36.  
  37. void Read_PBM_Image(IMAGE *Image,char *name);
  38.  
  39. FILE_HANDLE *Get_PBM_File_Handle()
  40.   {
  41.   FILE_HANDLE *handle;
  42.  
  43.   if ((handle = (FILE_HANDLE *) malloc(sizeof(FILE_HANDLE))) == NULL) 
  44.     {
  45.     fprintf (stderr, "Cannot allocate memory for output file handle\n");
  46.     return(NULL);
  47.     }
  48.  
  49.   handle->Default_File_Name_p = Default_PBM_File_Name;
  50.   handle->Open_File_p         = Open_PBM_File;
  51.   handle->Write_Line_p        = Write_PBM_Line;
  52.   handle->Read_Line_p         = Read_PBM_Line;
  53.   handle->Read_Image_p        = Read_PBM_Image;
  54.   handle->Close_File_p        = Close_PBM_File;
  55.   return (handle);
  56.   }
  57.  
  58. char *Default_PBM_File_Name()
  59.   {
  60.   return ("data.ppm");
  61.   }
  62.  
  63. int Open_PBM_File (handle, name, width, height, buffer_size, mode)
  64. FILE_HANDLE *handle;
  65. char *name;
  66. int *width;
  67. int *height;
  68. int buffer_size;
  69. int mode;
  70.   {
  71.   int data1, data2;
  72.  
  73.   handle->mode = mode;
  74.   handle->filename = name;
  75.  
  76.   switch (mode) 
  77.   {
  78.   case READ_MODE:
  79.  
  80.     if ((handle->file = fopen (name, READ_FILE_STRING)) == NULL) 
  81.       {
  82.       return(0);
  83.       }
  84.  
  85.     if (buffer_size != 0) 
  86.       {
  87.       if ((handle->buffer = malloc (buffer_size)) == NULL)
  88.         return(0);
  89.  
  90.       setvbuf (handle->file, handle->buffer, _IOFBF, buffer_size);
  91.       }
  92.  
  93.     if (((data1 = getc(handle->file)) == EOF)
  94.       || ((data2 = getc(handle->file)) == EOF))
  95.       return(0);
  96.  
  97.     if((data1 != 'P') || (data2 != '6')) return (0);
  98.  
  99.     if((data1 = getc(handle->file)) == EOF) return (0);
  100.  
  101.     printf("!");
  102.  
  103.     data2 = 0;
  104.     data1 = 0;
  105.  
  106.     do
  107.     {
  108.        data2 *= 10;
  109.        data2 += (data1-48);
  110.  
  111.          if((data1 = getc(handle->file)) == EOF) return (0);   
  112.  
  113.     }while((data1 >= '0') && (data1 <= '9'));
  114.  
  115.     *width = data2;
  116.  
  117.     data2 = 0;
  118.     data1 = 0;
  119.  
  120.     do
  121.     {
  122.        data2 *= 10;
  123.        data2 += (data1-48);
  124.  
  125.          if((data1 = getc(handle->file)) == EOF) return (0);   
  126.  
  127.     }while((data1 >= '0') && (data1 <= '9'));
  128.  
  129.     *height = data2;
  130.  
  131.     data2 = 0;
  132.     data1 = 0;
  133.  
  134.     do
  135.     {
  136.        data2 *= 10;
  137.        data2 += (data1-48);
  138.  
  139.          if((data1 = getc(handle->file)) == EOF) return (0);   
  140.  
  141.     }while((data1 >= '0') && (data1 <= '9'));
  142.  
  143.     if(data2 != 255) return (0);
  144.  
  145.     handle->width = *width;
  146.     handle->height = *height;
  147.     handle->buffer_size = buffer_size;
  148.     break;
  149.  
  150.   case WRITE_MODE:
  151.     if ((handle->file = fopen (name, WRITE_FILE_STRING)) == NULL)
  152.       return(0);
  153.  
  154.     if (buffer_size != 0) 
  155.       {
  156.       if ((handle->buffer = malloc (buffer_size)) == NULL)
  157.         return(0);
  158.  
  159.       setvbuf (handle->file, handle->buffer, _IOFBF, buffer_size);
  160.       }
  161.  
  162.     fprintf(handle->file,"P6\n%d %d\n%d\n",*width,*height,255);
  163.  
  164.     handle->width = *width;
  165.     handle->height = *height;
  166.     handle->buffer_size = buffer_size;
  167.  
  168.     break;
  169.  
  170.   case APPEND_MODE:
  171.     if ((handle->file = fopen (name, APPEND_FILE_STRING)) == NULL)
  172.       return(0);
  173.  
  174.     if (buffer_size != 0) 
  175.       {
  176.       if ((handle->buffer = malloc (buffer_size)) == NULL)
  177.         return(0);
  178.  
  179.       setvbuf (handle->file, handle->buffer, _IOFBF, buffer_size);
  180.       }
  181.  
  182.     handle->buffer_size = buffer_size;
  183.     break;
  184.   }
  185.   return(1);
  186.   }
  187.  
  188. void Write_PBM_Line (handle, line_data, line_number)
  189. FILE_HANDLE *handle;
  190. COLOUR *line_data;
  191. int line_number;
  192.   {
  193.   register int x;
  194.  
  195.   for (x = 0 ; x < handle->width ; x++)
  196.   {
  197.     fputc((int) floor (line_data[x].Red * 255.0), handle->file);
  198.     fputc((int) floor (line_data[x].Green * 255.0), handle->file);
  199.     fputc((int) floor (line_data[x].Blue * 255.0), handle->file);
  200.   }
  201.  
  202.   if (handle->buffer_size == 0) 
  203.     {
  204.     fflush(handle->file);                       /* close and reopen file for */
  205.     handle->file = freopen(handle->filename, APPEND_FILE_STRING,
  206.       handle->file);                /* integrity in case we crash*/
  207.     }
  208.   }
  209.  
  210. int Read_PBM_Line (handle, line_data, line_number)
  211. FILE_HANDLE *handle;
  212. COLOUR *line_data;
  213. int *line_number;
  214.   {
  215.   int data, i, c;
  216.  
  217.   for (i = 0 ; i < handle->width ; i++) 
  218.     {
  219.     if ((data = getc(handle->file)) == EOF)
  220.       return(-1);
  221.  
  222.     line_data[i].Red = (DBL) data / 255.0;
  223.  
  224.     if ((data = getc(handle->file)) == EOF)
  225.       return(-1);
  226.  
  227.     line_data[i].Green = (DBL) data / 255.0;
  228.  
  229.     if ((data = getc(handle->file)) == EOF)
  230.       return(-1);
  231.  
  232.     line_data[i].Blue = (DBL) data / 255.0;
  233.     }
  234.  
  235.   return (1);
  236.   }
  237.  
  238. int Read_PBM_Int_Line (handle, line_data, line_number)
  239. FILE_HANDLE *handle;
  240. IMAGE_LINE *line_data;
  241. int *line_number;
  242.   {
  243.   int data, i, c;
  244.  
  245.   if(*line_number == handle->height) return 0;
  246.  
  247.   if (((line_data->red = (unsigned char *) malloc(handle->width))==NULL) ||
  248.     ((line_data->green = (unsigned char *) malloc(handle->width))==NULL) ||
  249.     ((line_data->blue = (unsigned char *) malloc(handle->width))==NULL)) 
  250.     {
  251.     fprintf (stderr, "Cannot allocate memory for picture: %s\n", handle->filename);
  252.     close_all();
  253.     exit(1);
  254.     }
  255.  
  256.   for (i = 0 ; i < handle->width ; i++) 
  257.     {
  258.     line_data->red[i] = 0;
  259.     line_data->green[i] = 0;
  260.     line_data->blue[i] = 0;
  261.     }
  262.  
  263.   for (i = 0 ; i < handle->width ; i++) 
  264.     {
  265.     if ((data = getc(handle->file)) == EOF)
  266.       return(-1);
  267.  
  268.     line_data->red[i] = (unsigned char) data;
  269.  
  270.     if ((data = getc(handle->file)) == EOF)
  271.       return(-1);
  272.  
  273.     line_data->green[i] = (unsigned char) data;
  274.  
  275.     if ((data = getc(handle->file)) == EOF)
  276.       return(-1);
  277.  
  278.     line_data->blue[i] = (unsigned char) data;
  279.     }
  280.  
  281.   return (1);
  282.   }
  283.  
  284. void Close_PBM_File (handle)
  285. FILE_HANDLE *handle;
  286.   {
  287.   if(handle->file)
  288.     fclose (handle->file);
  289.   if (handle->buffer_size != 0)
  290.     free (handle->buffer);
  291.   }
  292.  
  293. void Read_PBM_Image(Image, name)
  294. IMAGE *Image;
  295. char *name;
  296.   {
  297.   int rc, row, data1, data2;
  298.   struct Image_Line line;
  299.   FILE_HANDLE handle;
  300.  
  301.   if ((handle.file = Locate_File (name, READ_FILE_STRING)) == NULL) 
  302.     {
  303.     fprintf (stderr, "Cannot open pbm file %s\n", name);
  304.     close_all();
  305.     exit(1);
  306.     }
  307.  
  308.   if (((data1 = getc(handle.file)) == EOF)
  309.     || ((data2 = getc(handle.file)) == EOF)) 
  310.     {
  311.  
  312.     fprintf (stderr, "Cannot open pbm file %s\n", name);
  313.     close_all();
  314.     exit(1);
  315.     }
  316.  
  317.     if((data1 != 'P') || (data2 != '6'))
  318.     {
  319.  
  320.     fprintf (stderr, "File %s is no pbmfile.\n", name);
  321.     close_all();
  322.     exit(1);
  323.     }
  324.  
  325.     if((data1 = getc(handle.file)) == EOF) return (0);
  326.  
  327.     data2 = 0;
  328.     data1 = 48;
  329.  
  330.     do
  331.     {
  332.        data2 *= 10;
  333.        data2 += data1-48;
  334.  
  335.          if((data1 = getc(handle.file)) == EOF) return (0);   
  336.        
  337.     }while((data1 >= '0') && (data1 <= '9'));
  338.  
  339.     Image->iwidth = data2;
  340.  
  341.     data2 = 0;
  342.     data1 = 48;
  343.  
  344.     do
  345.     {
  346.        data2 *= 10;
  347.        data2 += (data1-48);
  348.  
  349.          if((data1 = getc(handle.file)) == EOF) return (0);   
  350.         
  351.  
  352.     }while((data1 >= '0') && (data1 <= '9'));
  353.  
  354.     Image->iheight = data2;
  355.  
  356.     data2 = 0;
  357.     data1 = 48;
  358.  
  359.     do
  360.     {
  361.        data2 *= 10;
  362.        data2 += (data1-48);
  363.  
  364.          if((data1 = getc(handle.file)) == EOF) return (0);   
  365.  
  366.     }while((data1 >= '0') && (data1 <= '9'));
  367.  
  368.   if(data2 != 255)
  369.   {
  370.     fprintf (stderr, "Pbm file %s of wrong scale.\n", name);
  371.     close_all();
  372.     exit(1);
  373.     }
  374.  
  375.   Image->width = (DBL)Image->iwidth;
  376.   Image->height = (DBL)Image->iheight;
  377.   handle.filename = name; 
  378.   handle.width = Image->iwidth;
  379.   handle.height = Image->iheight;
  380.  
  381.   Image->Colour_Map_Size = 0;
  382.   Image->Colour_Map = NULL;
  383.  
  384.   if ((Image->data.rgb_lines = (struct Image_Line *)
  385.     malloc(Image->iheight * sizeof (struct Image_Line))) == NULL) 
  386.     {
  387.     fprintf (stderr, "Cannot allocate memory for picture: %s\n", name);
  388.     exit(1);
  389.     }
  390.  
  391.   row=0;
  392.  
  393.   while ((rc = Read_PBM_Int_Line(&handle, &line, &row)) == 1)
  394.   {
  395.     Image->data.rgb_lines[row] = line;
  396.     row++;
  397.   }
  398.  
  399.   fprintf(stdout,"%d\n",row);
  400.  
  401.   fclose (handle.file);
  402.  
  403.   if (rc == 0)
  404.     return;
  405.   else 
  406.     {
  407.     close_all();
  408.     exit(1);
  409.     }
  410.   }
  411.